#pragma once 
#include <bits/stdc++.h>


/***********************************************************************************************
 * @brief 概述
 *  C++11 增加了一个新的类型，称为右值引用(R-Value Reference), 标记为: T&&;
 * 
 *     左值: 表达式结束后依然存在的值；
 *     右值: 表达式结束后就不存在的值;
 *           一个区分左值和右值的方式是看能否对其取地址，所有的具名变量都是左值，否则是右值
 *     C++11 右值包括： 
 *           1). 将亡值(Expiring Value): 将要被移动的对象， T&&返回值
 *           2). 纯右值(Pure RValue)   : 函数非引用返回的临时变量， 运算表示产生的临时变量，
 *               原始字面量， lambda表达式等都是纯右值
 *     C++11中的所有值, 必须属于左值、将亡值、纯右值之一.
 * ============================================================
 * 
 * @brief && 的特性
 *   右值引用就是读第一个右值进行引用的类型，因为右值不具名，所以只能通过引用的方式找到它.
 *   
 *!  声明: 无论是声明的左值引用还是右值引用，都必须立即初始化它， 因为因为引用类型本身不拥有所绑定对象的内存，只
 *!        是该对象的一个别名。通过右值应用的声明， 该右值又"重获新生", 其声明周期与该右值引用变量的生命周期一样.
 *!        只要该变量名还活着，该右临时支将会一直活下去. 
 * 
 * 
 *********************************************************************************************/

int g_constructCount       = 0;     // 构造函数执行次数
int g_copyConstructCount   = 0;     // 拷贝构造函数执行次数
int g_destructCount        = 0;     // 析构函数执行次数

const char* RED_START   = "\033[31m";
const char* COLOR_RESET = "\033[0m";

struct A {
    A () {
        printf("%s构造函数执行了: %2d次%s\n", RED_START, ++g_constructCount, COLOR_RESET);
    }

    A (const A& other) {
        printf("%s拷贝构造函数执行了: %2d次%s\n", RED_START, ++g_copyConstructCount, COLOR_RESET);
    }

    ~A() {
        printf("%s析构函数执行了: %2d次%s\n",  RED_START, ++g_destructCount, COLOR_RESET);
    }
};


A getA () {
    return A();
}

A&& getAA () {
    return A();
}

template<typename T>
void func(T&& param) {
    printf("%s %s(%d)%s\n",  RED_START, __FUNCTION__, param, COLOR_RESET);
}


void printValue(int& i) {
    std::cout << RED_START << "lvalule: " << i << COLOR_RESET << std::endl;
}

void printValue(int&& i) {
    std::cout << RED_START << "rvalule: " << i << COLOR_RESET << std::endl;
}

void forward(int&& i) {
    //! 已命名的右值变成左值
    printValue(i);
}

void perfectForward(int&& i) {
    //! 完美转发
    printValue(std::forward<int>(i));
}


class B {
public:
    B() : _ptr(new int(0))  {
        std::cout << "construct" << std::endl;
    }

    //! 增加深拷贝的构造函数
    B(const B& other) : _ptr (new int(*(other._ptr))){
        std::cout << "copy construct" << std::endl;
    }

    //! 单独实现移动拷贝构造函数
    B(B&& other) : _ptr( other._ptr ){
        other._ptr = nullptr;             //! 特别注意
        std::cout << "move construct" << std::endl;
    }

    ~B() { 
        std::cout << "destruct" << std::endl;
        // delete _ptr; 
        //! 实现右值拷贝构造后，避免重复析构
        if (_ptr != nullptr) {
            delete _ptr;
        }
    }
private:
    int* _ptr;
};


B getB(bool flag = false) {
    B b;
    return b;
}

B&& getBB(bool flag = false) {
    B b;
    return std::move(b);
}

int rvalue_ref();